/**
 * 创建映射map
 * @param className 选择器
 * @param styles 动画样式
 * @returns 返回值如下
 * {
 *     dom1:  {
 *         transform: `translateY(${createAnimation(0,200,50,100)}px)`,
 *         opacity: createAnimation(0,200,0,1)
 *     },
 *     dom2:  {
 *         transform: `translateY(${createAnimation(0,200,50,100)}px)`,
 *         opacity: createAnimation(0,200,0,1)
 *     },
 * }
 */
function generateAnimationMap(className, styles){
    const domArr = document.querySelectorAll(className)
    
    if(!domArr){
        return null
        
    }
    
    let animationMap = new Map()
    for(const dom of domArr){
        animationMap.set(dom, Object.assign({}, styles))
    }
    return animationMap
}

/**
 * 获取map,便利dom元素,并调用dom每一个样式属性的方法,更新其数值
 * @param animationMap
 */
function updateStyles(animationMap){
    if(!animationMap){
        return
    }
    const scrollY = window.scrollY
    
    for(const [ dom, animations ] of animationMap){
        for(const prop in animations){
            dom.style[prop] = animations[prop](scrollY)
        }
    }
}

/**
 * 创建动画映射函数
 * @param scrollStart 滚动起始位置
 * @param scrollEnd 滚动结束位置
 * @param startValue 起始值
 * @param endValue 结束值
 * @returns {(function(*): (*))|*} 符合动画曲线的,用于输入位置,计算结果的函数
 * @example 输入(0, 300, 0, 1) 获得一个在0~300之间生效,结果为0~1的数值. 返回值为一个接收一个位置x,返回一个数值的函数.
 */
export function createAnimation(scrollStart, scrollEnd, startValue, endValue){
    return function(x){
        if(x < scrollStart){
            return startValue
        }
        if(x > scrollEnd){
            return endValue
        }
        
        return startValue + (endValue - startValue) * (x - scrollStart) / (scrollEnd - scrollStart)
    }
}

/**
 * 滚动动画
 * @param className 选择器,如 .box
 * @param styles 样式,如下
 * {
 *     dom1:  {
 *         transform: `translateY(${createAnimation(0,200,50,100)}px)`,
 *         opacity: createAnimation(0,200,0,1)
 *     },
 *     dom2:  {
 *         transform: `translateY(${createAnimation(0,200,50,100)}px)`,
 *         opacity: createAnimation(0,200,0,1)
 *     },
 * }
 */
export function goScrollAnimation(className, styles){
    let map = generateAnimationMap(className, styles)
    if(!map){
        return
    }
    updateStyles(map)
    window.addEventListener("scroll", (e) => {
        updateStyles(map)
    })
}

/**
 * 固定滚动的步长
 */
export function goScrollOneScreen(scrollStep){
    
    let go = (direction) => {
        // 当前位置
        const currentPosition = window.pageYOffset || document.documentElement.scrollTop
        let targetScrollTop   = currentPosition
        
        if(direction === "down"){ // 向下滚动
            targetScrollTop = Math.ceil(currentPosition / scrollStep) * scrollStep
        }
        else{ // 向上滚动
            targetScrollTop = Math.floor(currentPosition / scrollStep) * scrollStep
        }
        
        // 平滑滚动到目标位置
        window.scrollTo({ top: targetScrollTop, behavior: "smooth" })
    }
    
    // 监听滚轮方向
    document.addEventListener("wheel", (event) => {
        if(event.deltaY > 0){
            setTimeout(() => go("down"), 200)
        }
        else if(event.deltaY < 0){
            setTimeout(() => go("up"), 200)
        }
        else{
            console.log("未滚动")
        }
    })
}
